#include "Component.h"
#include "Node.h"
#include <fstream>
#include <random>
#include <unordered_set>
#include <algorithm>
#include <ctime>
#include <iomanip>

using namespace std;

class NetGraph
{
public:
    NetGraph(vector<Component *> comps, int id)
    {
        this->id = id;
        this->gen = mt19937(rd());
        this->components = comps;
        this->unconnectedComponents = components.size();
        shuffle(components.begin(), components.end(), default_random_engine(static_cast<unsigned int>(time(nullptr))));
        int numComps = components.size();
        for (int i = 0; i < numComps; i++, unconnectedComponents--)
        {
            // 跳过短路元件
            if (components[i]->is_shorted())
                continue;
            connect_component(components[i]);
        }
        // 处理短路元件和开路元件
        for (int i = 0; i < numComps; i++)
        {
            // 短路元件：两端连接到同一节点
            if (components[i]->is_shorted())
            {
                uniform_int_distribution<> dis(0, nodes.size() - 1);
                int nodeId;
                nodeId = nodes[dis(gen)]->id;
                Node *node = get_node(nodeId);
                components[i]->set_nodes(node, node);
                node->add_component(components[i]);
                cerr << "Warning: Shorted component: " << components[i]->get_name() << endl;
            }
            // 开路节点：选取一个已有节点，再创建一个新节点（悬浮）
            if (components[i]->is_open())
            {
                uniform_int_distribution<> dis(0, nodes.size() - 1);
                int nodeId1, nodeId2;
                nodeId1 = nodes[dis(gen)]->id;
                Node *node1 = get_node(nodeId1);
                Node *node2 = new Node(nextNodeId);
                nodes.push_back(node2);
                components[i]->set_nodes(node1, node2);
                node1->add_component(components[i]);
                node2->add_component(components[i]);
                nextNodeId++;
                cerr << "Warning: Open component: " << components[i]->get_name() << endl;
            }
        }
    }

    bool is_registered(int nodeId)
    {
        for (int i = 0; i < nodes.size(); i++)
        {
            if (nodes[i]->id == nodeId)
                return true;
        }
        return false;
    }

    vector<Node *> get_nodes()
    {
        return nodes;
    }

    Node *get_node(int nodeId)
    {
        for (int i = 0; i < nodes.size(); i++)
        {
            if (nodes[i]->id == nodeId)
                return nodes[i];
        }
        return nullptr;
    }

    pair<int, int> allocate_nodes()
    {
        int nodeId1, nodeId2;
        vector<int> invalidIds = invalid_node_ids();
        // cout << "size of invalidIds: " << invalidIds.size() << endl;
        // for (int i = 0; i < invalidIds.size(); i++)
        // {
        //     cout << "Invalid node id: " << invalidIds[i] << endl;
        // }

        // 如果只有一个未连接的元件，则尽量分配两个开路节点, 确保不添加新节点
        if (unconnectedComponents == 1)
        {
            if (invalidIds.size() == 2)
            {
                nodeId1 = invalidIds[0];
                nodeId2 = invalidIds[1];
            }
            else if (invalidIds.size() == 1)
            {
                nodeId1 = invalidIds[0];
                uniform_int_distribution<> dis(0, nodes.size() - 1);
                nodeId2 = nodes[dis(gen)]->id;
                while (nodeId1 == nodeId2)
                {
                    nodeId2 = nodes[dis(gen)]->id;
                }
            }
            else
            {
                uniform_int_distribution<> dis(0, nodes.size() - 1);
                nodeId1 = nodes[dis(gen)]->id;
                nodeId2 = nodes[dis(gen)]->id;
                while (nodeId1 == nodeId2)
                {
                    nodeId2 = nodes[dis(gen)]->id;
                }
            }
        }
        // n个元件最多可以连接到2n个开路节点，如果未连接的元件个数小于等于开路节点数的一半，那么接下来的每个元件都需要连到开路节点上
        else if (unconnectedComponents <= 2 * invalidIds.size())
        { // 这里开路节点数至少为1
            if (invalidIds.size() == 1)
            {
                nodeId1 = invalidIds[0];
                uniform_int_distribution<> dis(0, nodes.size() - 1);
                nodeId2 = nodes[dis(gen)]->id;
                while (nodeId1 == nodeId2)
                {
                    nodeId2 = nodes[dis(gen)]->id;
                }
            }
            else
            {
                uniform_int_distribution<> dis(0, invalidIds.size() - 1);
                nodeId1 = invalidIds[dis(gen)];
                nodeId2 = invalidIds[dis(gen)];
                // 确保 node1 和 node2 不相同
                while (nodeId1 == nodeId2)
                {
                    nodeId2 = invalidIds[dis(gen)];
                }
            }
        }
        // 否则随机选择节点：新建或选择已有的开路/非开路节点
        else
        {
            uniform_int_distribution<> dis(0, nextNodeId);
            nodeId1 = dis(gen);
            nodeId2 = dis(gen);
            // 确保 node1 和 node2 不相同
            while (nodeId1 == nodeId2)
            {
                nodeId2 = dis(gen);
            }
        }

        // 更新已使用的节点
        if (!is_registered(nodeId1))
        {
            Node *node1 = new Node(nodeId1);
            nodes.push_back(node1);
        }
        if (!is_registered(nodeId2))
        {
            Node *node2 = new Node(nodeId2);
            nodes.push_back(node2);
        }

        // 如果需要新节点，增加节点编号
        if (nodeId1 == nextNodeId || nodeId2 == nextNodeId)
        {
            nextNodeId++;
        }

        return {nodeId1, nodeId2};
    }

    void connect_component(Component *c)
    {
        auto [nodeId1, nodeId2] = allocate_nodes();
        Node *node1 = get_node(nodeId1);
        Node *node2 = get_node(nodeId2);
        c->set_nodes(node1, node2);
        node1->add_component(c);
        node2->add_component(c);
    }

    void print_netlist()
    {
        for (int i = 0; i < components.size(); i++)
        {
            cout << components[i]->get_name() << "\t"
                 << components[i]->get_node1()->id << "\t"
                 << components[i]->get_node2()->id << "\t"
                 << scientific << setprecision(1)
                 << components[i]->get_value() << endl;
        }
        cout << endl;
    }
    // 新增的重载方法，输出到文件流
    void print_netlist(ofstream &out) const
    {
        out << ".net" << id << endl;
        for (int i = 0; i < components.size(); i++)
        {
            out << components[i]->get_name() << "\t"
                << components[i]->get_node1()->id << "\t"
                << components[i]->get_node2()->id << "\t"
                << scientific << setprecision(1)
                << components[i]->get_value() << endl;
        }
        out << endl;
    }

private:
    vector<int> invalid_node_ids()
    {
        vector<int> ids;
        for (int i = 0; i < nodes.size(); i++)
        {
            if (nodes[i]->numComponents < 2)
                ids.push_back(nodes[i]->id);
        }
        return ids;
    }

private:
    vector<Node *> nodes;
    vector<Component *> components;
    int id;
    int nextNodeId = 1;
    int unconnectedComponents;
    // 随机数生成器
    random_device rd;
    mt19937 gen;
};